package com.sc.byahi.user.client;

import java.util.Date;
import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sc.byahi.user.client.components.rating.NewRating;
import com.sc.byahi.user.shared.Profile;
import com.sc.byahi.user.shared.ProfileMetadata;
import com.sc.byahi.user.shared.ProfileOwner;
import com.sc.byahi.user.shared.SharedUtil;
import com.sc.byahi.user.shared.constants.Config;

public class ProfileViewDiv extends Composite {

	private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

	interface MyUiBinder extends UiBinder<Widget, ProfileViewDiv> {
	}

	private int currImageNo = 0;
	boolean isMap = false;
	Boolean ownData;// Object so that if it is unset, it throws Exception
	Profile p = null;
	//If read only is true, all buttons are invisible
	boolean readOnly = false;

	@UiField
	Image isAgent;
	@UiField
	Image thumb;
	@UiField
	Image left;
	boolean leftEnabled;
	@UiField
	Image right;
	boolean rightEnabled;
	@UiField
	SpanElement bloodgroup;
	@UiField
	SpanElement row1;
	@UiField
	SpanElement row2;
	@UiField
	SpanElement row3;
	@UiField
	SpanElement row4;
	@UiField
	SpanElement row5;
	@UiField
	Image manglik;
	@UiField
	Image smoke;
	@UiField
	Image diet;
	@UiField
	Image imgPhysicalStatusDetail;
	@UiField
	Image imageInt;
	@UiField
	Label info;
	@UiField
	Label profileId;
	@UiField
	Button btnApprove;
	@UiField
	Button btnDisapprove;
	@UiField
	Button btnEdit;
	@UiField
	Button btnPicUpload;
	@UiField
	Button btnSendMessage;
	@UiField
	Button btnSendInterest;
	@UiField
	Button btnAccInterest;
	@UiField
	Button btnHoldInterest;
	@UiField
	DisclosurePanel disclosurePanel;
	@UiField
	NewRating rating = new NewRating();

	public ProfileViewDiv() {
		initWidget(uiBinder.createAndBindUi(this));
		rating.setDoubleClick(false);//redundent call, still...
		manglik.setUrl("/images/mars.png");
		bloodgroup.setAttribute("style", "vertical-align: top");
		row1.setAttribute("style", "display: block; clear: right;");
		row2.setAttribute("style", "display: block; clear: right;");
		row3.setAttribute("style", "display: block; clear: right;");
		row4.setAttribute("style", "display: block; clear: right;");
		row5.setAttribute("style", "display: block; clear: right;");
		initializeButtons();
	}

	public ProfileViewDiv(boolean isMap) {
		this();
		this.isMap = isMap;
	}

	private void showDiet(String dietText) {
		diet.setTitle(dietText);
		if ("Vegetarian".equals(dietText)) {
			diet.setUrl("/images/diet_veg.png");
		} else if ("Eggetarian".equals(dietText)) {
			diet.setUrl("/images/diet_egg.png");
		} else if ("Non Vegetarian".equals(dietText)) {
			diet.setUrl("/images/diet_nonveg.png");
		}
		diet.setVisible(true);
	}

	private void updateUIForInterestAction(String action) {
		imageInt.setVisible(true);

		btnSendMessage.setVisible(false);
		btnAccInterest.setVisible(false);
		btnHoldInterest.setVisible(false);

		if (ProfileMetadata.IA.equals(action)) {
			imageInt.setUrl("/images/int_acc.png");
			imageInt.setTitle("This person has accepted your interest.");
			btnSendMessage.setVisible(true);
		} else if (ProfileMetadata.RA.equals(action)) {
			imageInt.setUrl("/images/int_acc.png");
			imageInt.setTitle("You have accepted interest of this person.");
			btnSendMessage.setVisible(true);
		} else if (ProfileMetadata.IS.equals(action)) {
			imageInt.setUrl("/images/int.png");
			imageInt.setTitle("You have sent interest to this profile. Please wait for the person to take some action.");
		} else if (ProfileMetadata.IH.equals(action)) {
			imageInt.setUrl("/images/int_pend.png");
			imageInt.setTitle("This person has put your request on hold. This person might consider your profile once he/she has considers othe profiles. Please wait.");
			btnAccInterest.setVisible(true);
		} else if (ProfileMetadata.RH.equals(action)) {
			imageInt.setUrl("/images/int_pend.png");
			imageInt.setTitle("You have put this person's interest on hold. Press accept interest whenever you feel like contacting this person.");
			btnAccInterest.setVisible(true);
		} else if (ProfileMetadata.RR.equals(action)) {
			imageInt.setUrl("/images/int.png");
			imageInt.setTitle("You have received interest from this profile. Please take some action.");
			btnAccInterest.setVisible(true);
			btnHoldInterest.setVisible(true);
		}
	}

	private void showSmoking(String smokes) {
		if ("Yes".equals(smokes)) {
			smoke.setUrl("/images/smoking.png");
			smoke.setTitle("Smokes");
		} else if ("No".equals(smokes)) {
			smoke.setUrl("/images/smoking_no.png");
			smoke.setTitle("Non Smoker");
		}
		smoke.setVisible(true);
	}

	private void showPhysicalDetails(String disability) {
		if ("Physical Disability".equals(disability)) {
			imgPhysicalStatusDetail.setUrl("/images/phy_physical.png");
		}
		if ("Visual Impairment".equals(disability)) {
			imgPhysicalStatusDetail.setUrl("/images/phy_visual.png");
		}
		if ("Hearing/Speech Disorder".equals(disability)) {
			imgPhysicalStatusDetail.setUrl("/images/phy_vocal.png");
		}
		if ("Intellectual Disability".equals(disability)) {
			imgPhysicalStatusDetail.setUrl("/images/phy_mental.png");
		}
		imgPhysicalStatusDetail.setTitle(disability);
		imgPhysicalStatusDetail.setVisible(true);
	}

	private void showManglik(String ismanglik) {
		if ("Yes".equals(ismanglik)) {
			manglik.setVisible(true);
		}
	}

	private HTML wrapSpan(String text) {
		// return new HTML("<span style=\"display: inline; color:#66d\">"+text+ "</span>");
		return new HTML(text);
	}

	private void initializeButtons() {
		btnSendInterest.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				btnSendInterest.setEnabled(false);
				GreetingService.Util.getInstance().interestShow(AppController.get().getCurrentProfileId(), p.getId(), new AsyncCallback<Boolean>() {
					@Override
					public void onSuccess(Boolean result) {
						AppController.get().updateInterestDataForCurrProfileId(p.getId(), ProfileMetadata.IS);
						updateUIForInterestAction(ProfileMetadata.IS);
					}

					@Override
					public void onFailure(Throwable caught) {
						btnSendInterest.setEnabled(true);
						UIUtil.showGenericFailureDialog();
					}
				});
			}
		});
		btnAccInterest.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				btnAccInterest.setEnabled(false);
				GreetingService.Util.getInstance().interestAccept(AppController.get().getCurrentProfileId(), p.getId(), new AsyncCallback<Boolean>() {
					@Override
					public void onSuccess(Boolean result) {
						AppController.get().updateInterestDataForCurrProfileId(p.getId(), ProfileMetadata.RA);
						updateUIForInterestAction(ProfileMetadata.RA);
					}

					@Override
					public void onFailure(Throwable caught) {
						btnAccInterest.setEnabled(true);
						UIUtil.showGenericFailureDialog();
					}
				});

			}
		});

		btnHoldInterest.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				btnHoldInterest.setEnabled(false);
				GreetingService.Util.getInstance().interestHold(AppController.get().getCurrentProfileId(), p.getId(), new AsyncCallback<Boolean>() {
					@Override
					public void onSuccess(Boolean result) {
						AppController.get().updateInterestDataForCurrProfileId(p.getId(), ProfileMetadata.RH);
						updateUIForInterestAction(ProfileMetadata.RH);
					}

					@Override
					public void onFailure(Throwable caught) {
						btnHoldInterest.setEnabled(true);
						UIUtil.showGenericFailureDialog();
						
					}
				});

			}
		});
		right.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if (rightEnabled) {
					if (currImageNo < p.getImages().size() - 1)
						++currImageNo;
					showImage();
				}
			}
		});
		left.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if (leftEnabled) {
					if (currImageNo > 0)
						--currImageNo;
					showImage();
				}
			}
		});
		btnApprove.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {

				final Button src = (Button) event.getSource();
				GreetingService.Util.getInstance().approveProfile(p.getId(), new AsyncCallback<Boolean>() {
					@Override
					public void onSuccess(Boolean result) {
						if (result) {
							AppController.get().profileApprovalChanged(p.getId(), true);
							AppController.get().profileUpdated(p.getId(), isMap);
							src.setVisible(false);
							btnDisapprove.setVisible(true);
						}
					}

					@Override
					public void onFailure(Throwable caught) {
						src.setEnabled(true);
						UIUtil.showGenericFailureDialog();

					}
				});
			}
		});
		btnDisapprove.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {

				final Button src = (Button) event.getSource();
				GreetingService.Util.getInstance().disapproveProfile(p.getId(), new AsyncCallback<Boolean>() {
					@Override
					public void onSuccess(Boolean result) {
						if (result) {
							AppController.get().profileApprovalChanged(p.getId(), false);
							AppController.get().profileUpdated(p.getId(), isMap);
							src.setVisible(false);
							btnApprove.setVisible(true);
						}
					}

					@Override
					public void onFailure(Throwable caught) {
						src.setEnabled(true);
						UIUtil.showGenericFailureDialog();

					}
				});
			}
		});
		btnEdit.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				History.newItem("editprofile:" + p.getId().toString(), true);
			}
		});
		btnPicUpload.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				final PopupPanel popup = new PopupPanel();
//				popup.add(new PhotoUploadPopup(p.getId(), isMap));
				popup.add(new PhotoUploadView(p.getId(), isMap));
				popup.setGlassEnabled(true);
				popup.center();
			}
		});
		btnSendMessage.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				PopupPanel imagePopup = new PopupPanel(true);
//				imagePopup.setWidget(new EmailSender(p));
				imagePopup.setWidget(new EmailView(p.getId()));
				imagePopup.setGlassEnabled(true);
				imagePopup.center();
			}
		});
		// No handler is added to rating as it calls AppController directly.
		// rating.addValueChangeHandler(new ValueChangeHandler<Long>() {
		// @Override
		// public void onValueChange(ValueChangeEvent<Long> event) {
		// AppController.get().ratingChanged(p.getId(), rating.getValue());
		// }
		// });
		disclosurePanel.addOpenHandler(new OpenHandler<DisclosurePanel>() {
			@Override
			public void onOpen(OpenEvent<DisclosurePanel> event) {
				final FlexTable tab = createDetailTable(p);
				disclosurePanel.setContent(tab);
			}
		});

	}

	public void cleanForReuse() {
		isAgent.setVisible(false);
		profileId.setText("");
		info.setText("");
		info.setStyleName("approved");
		imageInt.setVisible(false);
		imgPhysicalStatusDetail.setVisible(false);
		manglik.setVisible(false);
		bloodgroup.setInnerText("");

		diet.setVisible(false);
		smoke.setVisible(false);
		rating.clean();
		rating.setVisible(false);
		currImageNo = 0;
		thumb.setUrl("/images/waiting.gif");
//		thumb.setUrl("/images/no-photo.png");

		row1.setInnerText("");
		row2.setInnerText("");
		row3.setInnerText("");
		row4.setInnerText("");
		row5.setInnerText("");

		btnApprove.setVisible(false);
		btnDisapprove.setVisible(false);
		btnEdit.setVisible(false);
		btnPicUpload.setVisible(false);
		btnSendMessage.setVisible(false);
		btnSendInterest.setVisible(false);
		btnAccInterest.setVisible(false);
		btnHoldInterest.setVisible(false);

		if (disclosurePanel != null)
			disclosurePanel.setContent(new Label(""));
	}

	@SuppressWarnings("unused")
	public void showData(final Profile profile) {
		this.p = profile;
		profileid: {
			if (p.getOwnerAgency())
				isAgent.setVisible(true);

			profileId.setText(p.getId() + ": " + p.getName());
			showDiet(p.getEatingHabits());
			showSmoking(p.getSmoking());
			showManglik(p.getManglik());
			bloodgroup.setInnerText(p.getBloodGroup());
			if (!"Normal".equals(p.getPhysicalStatus())) {
				showPhysicalDetails(p.getPhysicalStatusDetail());
			}
		}
		icons: {
			if (!"".equals(p.getOwner()) && !p.getApproved()) {
				info.setText("Unapproved profile. Only approved profiles are visible to other users in search.");
				info.setStyleName("unapproved");
			} else {
				info.setStyleName("approved");
			}
		}
		infoText: {
			if (p.getImages().isEmpty()) {
				info.setText("Please upload photos. Profiles without photos will not be approved.");
				info.setStyleName("unapproved");
			}
		}
		image: {
			if (p.getImages().isEmpty()) {
				showNoImage();
			} else {
				// if (Util.imageFromURL) {
				// this.blobKeys = p.getImageURLs();
				// } else {
				// this.blobKeys = p.getImages();
				// }
				thumb.addClickHandler(new ClickHandler() {
					public void onClick(ClickEvent event) {
						PopupPanel imagePopup = new PopupPanel(true);
						imagePopup.setGlassEnabled(true);
						// imagePopup.setWidget(new PhotoViewer(blobKeys));
						String url = "";
						imagePopup.setWidget(new PhotoViewDiv(Config.imageFromURL? p.getImageURLs() : p.getImages()));
						imagePopup.center();
					}
				});
				showImage();
			}
		}
		descrow1: {
			StringBuffer sb = new StringBuffer();

			Date currDate = new Date();
			Date dob = p.getDob();
			@SuppressWarnings("deprecation")
			int age = currDate.getYear() - dob.getYear();
			@SuppressWarnings("deprecation")
			int diff = currDate.getMonth() - dob.getMonth();

			if (diff < 0) {
				age--;
			}
			sb.append(age).append(wrapSpan(" yrs, ")).append(p.getGender()).append(", ").append(UIUtil.inchesToFtInString(p.getHeight()));

			if (!"Unmarried".equals(p.getMaritalStatus())) {
				sb.append(", ").append(p.getMaritalStatus()).append(", ").append(wrapSpan("Children: ")).append(p.getMaritalStatusChildren());
			} else {
				sb.append(", ").append(p.getMaritalStatus());
			}
			// TODO: check data validaton for html xss
			// row1.setInnerHTML(SafeHtmlUtils.fromString(sb.toString()).asString());
			row1.setInnerHTML(sb.toString());
		}
		descrow2: {
			StringBuffer sb = new StringBuffer();
			sb.append(p.getReligion()).append(", ").append(p.getCaste()).append(", ").append(wrapSpan("mother tongue is ")).append(p.getMotherTongue());
			if (!p.getLanguages().isEmpty()) {
				sb.append(", ").append(wrapSpan("speaks ")).append(SharedUtil.getCSV(p.getLanguages()));
			}
			// row2.setInnerHTML(SafeHtmlUtils.fromString(sb.toString()).asString());
			// TODO: check if the saved values are part of list and no HTML scripts are embedded
			row2.setInnerHTML(sb.toString());
		}
		descrow3: {
			StringBuffer sb = new StringBuffer();
			sb.append(SharedUtil.getCSV(p.getDegrees())).append(", ").append(wrapSpan("works in ")).append(p.getEmploymentType());
			// row3.setInnerHTML(SafeHtmlUtils.fromString(sb.toString()).asString());
			// TODO: validat
			row3.setInnerHTML(sb.toString());
		}

		descrow4: {
			StringBuffer sb = new StringBuffer();
//			String loc = p.getCurrCity() + ", " + p.getCurrState() + ", " + p.getCurrCountry();
//			if (p.getCurrCity().trim().equals("") && p.getCurrState().trim().equals("") && p.getCurrCountry().trim().equals("")) {
//				loc = p.getCurrGeoAddress();
//			}
//			sb.append(loc);
			sb.append(p.getCurrGeoAddress());
			// row4.setInnerHTML(SafeHtmlUtils.fromString(loc).asString());
			row4.setInnerHTML(sb.toString());
		}
		descrow5: {
			StringBuffer sb = new StringBuffer();
			sb.append(wrapSpan("Family: "));
			if ("No".equals(p.getFamilyLivingWithMe())) {
				String famLoc = p.getFamCity() + ", " + p.getFamState() + ", " + p.getFamCountry();
				if (p.getFamCity().trim().equals("") && p.getFamState().trim().equals("") && p.getFamCountry().trim().equals("")) {
					famLoc = p.getCurrGeoAddress();
				}
				sb.append(famLoc);
			} else {
				if (p.getGender().equals("Male")) {
					sb.append("Joint family");
				} else if (p.getGender().equals("Female")) {
					sb.append("Lives with parents");
				}
			}
			// row5.setInnerHTML(SafeHtmlUtils.fromString(sb.toString()).asString());
			row5.setInnerHTML(sb.toString());
		}
		approve: {
			if (AppController.get().getCurrentUserAdmin() && !p.getApproved()) {
				btnApprove.setVisible(true);
			}
			if (AppController.get().getCurrentUserAdmin() && p.getApproved()) {
				btnDisapprove.setVisible(true);
			}

		}

		selfProfile: {
			if (!"".equals(p.getOwner()) && !readOnly) {
				btnEdit.setVisible(true);
				btnPicUpload.setVisible(true);
			}
		}
		messaging: {
			Map<Long, String> data = AppController.get().getInterestDataForCurrProfileId();
			boolean hasData = data.containsKey(p.getId());
			if (hasData) {
				boolean intAcc = data.get(p.getId()).equals(ProfileMetadata.RA);
				boolean reqAcc = data.get(p.getId()).equals(ProfileMetadata.IA);
				if ((intAcc || reqAcc) && !ownData && !readOnly) {
					btnSendMessage.setVisible(true);
				}
			}
		}

		rating: {
			// User must have at least one profile (even unapproved) to rate.
			ProfileOwner owner = AppController.get().getOwner();
			if ((!owner.getAllProfiles().isEmpty()) && !ownData && !readOnly) {
				rating.setVisible(true);
				rating.setProfileId(p.getId());
				Map<Long, Long> ratings = AppController.get().getRatings();
				Long ratingValue = new Long(Config.NO_RATING);
				if (ratings.containsKey(p.getId())) {
					ratingValue = ratings.get(p.getId());
				}
				// else {
				// ratings.put(p.getId(), ratingValue);
				// }
				rating.setInitValue(ratingValue);
			}
		}

		interest: {
			// If user has at least one approved profile, only then show it
			if (!AppController.get().getOwner().getApprovedProfiles().isEmpty() && !ownData && !readOnly) {
				final Map<Long, String> profileMetadata = AppController.get().getInterestDataForCurrProfileId();
				if (profileMetadata.containsKey(p.getId())) {
					String md = profileMetadata.get(p.getId());
					updateUIForInterestAction(md);
				} else {
					btnSendInterest.setVisible(true);
				}
			}
		}

		disclosurePanel.setOpen(false);

	}

	private void showImage() {
		String url = "";
		if (Config.imageFromURL) {
			url = UIUtil.getImageURLs(p.getImageURLs(), currImageNo, true);
		} else {
			url = UIUtil.getImageURLs(p.getImages(), currImageNo, true);
		}
		checkNav();
		thumb.setUrl(url);
	}

	private void showNoImage() {
		checkNav();
		thumb.setUrl("/images/no-photo.png");
	}

	private void checkNav() {

		if (currImageNo >= p.getImages().size() - 1) {
			right.setUrl("/images/1rightarrowbw.png");
			rightEnabled = false;
		} else {
			right.setUrl("/images/1rightarrow.png");
			rightEnabled = true;
		}
		if (currImageNo <= 0) {
			left.setUrl("/images/1leftarrowbw.png");
			leftEnabled = false;
		} else {
			left.setUrl("/images/1leftarrow.png");
			leftEnabled = true;
		}
	}

	private FlexTable createDetailTable(final Profile p) {
		final FlexTable tab = new FlexTable();
		tab.setStyleName("profile-display-label");

		int row = 0;

		tab.setHTML(row, 0, "About me");
		tab.setHTML(row++, 1, p.getAboutMe());

		return tab;
	}

	public Boolean isOwnData() {
		return ownData;
	}

	public void setOwnData(Boolean ownData) {
		this.ownData = ownData;
	}

	public Profile getP() {
		return p;
	}

	public boolean isReadOnly() {
		return readOnly;
	}

	public void setReadOnly(boolean readOnly) {
		this.readOnly = readOnly;
	}
}